package tools

import (
	"database/sql"
	"fmt"
	"gdshop-admin-go-api/app/response/BaseResp"
	"gdshop-admin-go-api/library/response"
	"gdshop-admin-go-api/library/tools/genids"
	"github.com/gogf/gf/crypto/gmd5"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/util/gconv"
	"github.com/gogf/gf/util/grand"
	"math"
	"net"
	"strconv"
	"strings"
	"time"
)

func EncryptPassword(password string, passwordSalt string) string {
	pmd5, _ := gmd5.EncryptString(password)
	psmd5, _ := gmd5.EncryptString(passwordSalt)

	rmd5, _ := gmd5.EncryptString(pmd5 + psmd5)

	return rmd5
}

// EncryptPasswordHash 传入密码是已经经过md5加密了
func EncryptPasswordHash(password string, passwordSalt string) string {
	psmd5, _ := gmd5.EncryptString(passwordSalt)

	rmd5, _ := gmd5.EncryptString(password + psmd5)

	return rmd5
}

var vcodeKeyName = "gdshopVCode"

// 获取短信验证码 数字
func GetVCode(mobile string) string {
	length := 6
	conn := g.Redis().Conn()
	defer conn.Close()
	code := grand.Digits(length)
	conn.Do("HSET", vcodeKeyName, mobile, code)
	return code
}

// 验证 短信验证码
func VerifyVCode(mobile string, code string) bool {
	// 单元测试验证码
	if g.Cfg().GetBool("site.Debug") == true {
		return true
	}
	conn := g.Redis().Conn()
	defer conn.Close()
	v, _ := conn.DoVar("HGET", vcodeKeyName, mobile)
	return v.String() == code
}

var VCodeOftenName = "VCodeOftenName"

// 设置发送时间
func SetVCodeOften(mobile string) {
	conn := g.Redis().Conn()
	defer conn.Close()
	conn.Do("HSET", VCodeOftenName, mobile, time.Now().Unix())
}

// 检查验证码发送是否频繁，过期时间 60 秒 false=可以发送
func CheckVCodeOften(mobile string) bool {
	if g.Cfg().GetBool("site.Debug") == true {
		return false
	}
	conn := g.Redis().Conn()
	defer conn.Close()
	v, _ := conn.DoVar("HGET", VCodeOftenName, mobile)
	often := g.Cfg().GetInt64("site.VCodeOften", 60)
	if time.Now().Unix() > (v.Int64() + often) {
		return false
	} else {
		return true
	}
}

// 获取分页信息
func GetPageInfo(totalRows int, pageIndex int, pageSize int) BaseResp.PageInfo {
	// 需要转换为 float64
	totalPage := int(math.Ceil(float64(totalRows) / float64(pageSize)))
	return BaseResp.PageInfo{
		HasMore:     totalPage > pageIndex,
		PageIndex:   pageIndex,
		PageSize:    pageSize,
		TotalPage:   totalPage,
		TotalCount:  totalRows,
		IsFirstPage: pageIndex < 2,
		IsLastPage:  pageIndex > totalPage,
	}
}

func GetGoodsThumbs(thumbs string) []string {
	return strings.Split(thumbs, ",")
}

// 如果查询不到数据时，返回的处理，必须有错误才调用本方法
// err 错误
// message 返回消息
// isSuccess true返回成功，false返回失败
func GetErrNoRowsResponse(err error, message string, isSuccess bool) *response.JsonResponse {
	if err == sql.ErrNoRows {
		if isSuccess == true {
			return response.SuccessByRequestMessage(nil, message)
		} else {
			return response.FailByRequestMessage(nil, message)
		}
	}
	// 其他错误，必须返回错误
	return response.FailByRequestMessage(nil, err.Error())
}

func Decimal(value float64) float64 {
	value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", value), 64)
	return value
}

/**
 * 数组去重 去空
 */
func RemoveDuplicatesAndEmpty(a []string) (ret []string) {
	a_len := len(a)
	for i := 0; i < a_len; i++ {
		if (i > 0 && a[i-1] == a[i]) || len(a[i]) == 0 {
			continue
		}
		ret = append(ret, a[i])
	}
	return
}

// CategoryTypeStrToTypeIds 分类字符串转分类数字
func CategoryTypeStrToTypeIds(typeStr string) g.Slice {
	if typeStr == "cms" {
		return g.Slice{"1", "2", "3", "4"}
	}
	if typeStr == "shop" {
		return g.Slice{"5"}
	}

	return g.Slice{}
}

func inArrayString(need string, needArr []string) bool {
	for _, v := range needArr {
		if need == v {
			return true
		}
	}
	return false
}
func InArrayInt(need int, needArr []int) bool {
	for _, v := range needArr {
		if need == v {
			return true
		}
	}
	return false
}

func GetGoodsCatesText(cates string, categoryArr g.Map) string {
	tmps := strings.Split(cates, ",")
	fanhui := g.ArrayStr{}
	for key, item := range categoryArr {
		if inArrayString(key, tmps) {
			fanhui = append(fanhui, gconv.String(item))
		}
	}
	return strings.Join(fanhui, ",")
}

// CheckIps IP检测 IP过滤设置 ["127.0.0.1-127.0.0.255"]
func CheckIps(ip string, ipWhiteList []string) bool {
	var ipSlice []string
	for _, item := range ipWhiteList {
		ipSlice = strings.Split(item, `-`)
		if ip2Int(ip) >= ip2Int(ipSlice[0]) && ip2Int(ip) <= ip2Int(ipSlice[1]) {
			// 在列表
			return true
		}
	}

	return false
}

func ip2Int(ip string) int64 {
	if len(ip) == 0 {
		return 0
	}
	bits := strings.Split(ip, ".")
	if len(bits) < 4 {
		return 0
	}
	b0 := string2Int(bits[0])
	b1 := string2Int(bits[1])
	b2 := string2Int(bits[2])
	b3 := string2Int(bits[3])

	var sum int64
	sum += int64(b0) << 24
	sum += int64(b1) << 16
	sum += int64(b2) << 8
	sum += int64(b3)

	return sum
}

func string2Int(in string) (out int) {
	out, _ = strconv.Atoi(in)
	return
}

func MakeTimestamp() int64 {
	return time.Now().UnixNano() / int64(time.Millisecond)
}

func ClaerCacheByKeyPrefix(keyPrefix string) {
	doVar, err := g.Redis().DoVar("keys", keyPrefix)
	if err != nil {
		fmt.Println(err)
		return
	}
	g.Redis().Do("del", doVar.Array()...)
}

func GetInvoiceNo() (string, error) {
	orderNo, idErr := genids.ToolsGetNextId()
	if idErr != nil {
		return "", idErr
	}
	typeStr := "I"
	return gconv.String(time.Now().Year()) + typeStr + gconv.String(orderNo), nil
}

func GetMyIp() string {
	conn, err := net.Dial("udp", "baidu.com:80")
	if err != nil {
		fmt.Println(err.Error())
		return ""
	}
	defer conn.Close()
	return strings.Split(conn.LocalAddr().String(), ":")[0]
}
